//
//  CZEmoticonManager.swift
//  WeiBoComposeDemo
//
//  Created by Summer on 2017/12/19.
//  Copyright © 2017年 Vitas. All rights reserved.
//

import UIKit

class CZEmoticonManager {
    
    /// 表情管理器的单例
    static let shared = CZEmoticonManager()
    
    lazy var packages = [CZEmoticonPackage]()
    
    /// 表情素材的单例
    lazy var bundle: Bundle = {
       
        let path = Bundle.main.path(forResource: "HMEmoticon.bundle", ofType: nil)
        
        return Bundle(path: path!)!
        
    }()
    
    // 构造函数，如果在 init 之前增加 private 修饰符，可以要求调用者必须通过 shared 访问对象
    // OC 要重写 allocWithZone 方法
    private init() {
        loadPackages()
    }
    
}

// MARK: - 表情符号的处理
extension CZEmoticonManager {
    
    /// 将给定的字符串转换成属性文本
    /// - 关键点：要按照匹配结果倒序替换属性文本!
    /// - Parameter string: 完整的字符串
    /// - Returns: 属性文本
    func emoticonString(string: String, font: UIFont) -> NSAttributedString {
        
        let attrString = NSMutableAttributedString(string: string)
        
        // 1.建立正则表达式，过滤所有表情
        // [] ()都是正则表达式的关键字，如果参与匹配需要转义
        let pattern = "\\[.*?\\]"
        guard let regx = try? NSRegularExpression(pattern: pattern, options: []) else {
            return attrString
        }
        
        // 2.匹配所有项
        let matchs = regx.matches(in: string, options: [], range: NSRange(location: 0, length: string.count))
        
        // 3.遍历所有匹配结果(倒序遍历)
        for match in matchs.reversed() {
            let range = match.range(at: 0)
            print("location--\(range.location), length--\(range.length)")
            let subStr = (attrString.string as NSString).substring(with: range)
            
            // 1.查找对应的表情符号
            if let emoticon = CZEmoticonManager.shared.findEmoticon(string: subStr) {
                
                // 2.使用表情符号中的属性文本，替换原有的属性文本的内容
                attrString.replaceCharacters(in: range, with: emoticon.imageText(font: font))
            }
        }
        
        // 4.统一设置一遍字符串的属性，保证所有字体属性一致，否则行高等会出问题(非常重要)
        // 除了需要设置字体，还要设置颜色
        attrString.addAttributes(
            [
                NSAttributedStringKey.font: font,
                NSAttributedStringKey.foregroundColor: UIColor.darkGray
            ],
            range: NSRange(location: 0, length: attrString.length))
        
        return attrString
    }
    
    /// 根据 string [爱你] 在所有的表情符号中查找对应的表情模型对象
    ///
    /// - Parameter string: string
    /// - Returns: CZEmoticon/nil
    func findEmoticon(string: String) -> CZEmoticon? {
        
        // 遍历表情包
        // OC 中过滤数组，使用谓词
        // Swift 中更简单
        for p in packages {
            
            // 在表情数组中过滤 string
            // 方法1
//            let result = p.emoticons.filter({ (em) -> Bool in
//                return em.chs == string
//            })
            
            // 方法2 - 尾随闭包
//            let result = p.emoticons.filter(){ (em) -> Bool in
//                return em.chs == string
//            }
            
            // 方法3 - 如果闭包中只有一句，并且是返回  return em.chs == string
            // 1>闭包格式定义可以省略
            // 2>参数省略之后，使用$0,$1...依次替代原有的参数
//            let result = p.emoticons.filter(){
//                return $0.chs == string
//            }
            
            // 方法4 - 如果闭包中只有一句，并且是返回  return em.chs == string
            // 1>闭包格式定义可以省略
            // 2>参数省略之后，使用$0,$1...依次替代原有的参数
            // 4>return也可以省略
            let result = p.emoticons.filter(){ $0.chs == string }
            
            // 判断结果数组的数量
            if result.count == 1 {
                return result[0]
            }
            
        }
        
        return nil
    }
    
}


// MARK: - 表情包数据处理
fileprivate extension CZEmoticonManager {
    func loadPackages() {
        //读取 emoticons.plist
        //只要按照 Bundle 默认的结构目录设定，就可以直接读取 Resources 目录的文件
        guard let path = Bundle.main.path(forResource: "HMEmoticon", ofType: "bundle"),
            let bundle = Bundle(path: path),
            let plistPath = bundle.path(forResource: "emoticons", ofType: "plist"),
            let array = NSArray(contentsOfFile: plistPath) as? [[String:String]],
            let models = NSArray.yy_modelArray(with: CZEmoticonPackage.self, json: array) as? [CZEmoticonPackage] else {
                return
        }
        
        // 设置表情包数据
        // packages 懒加载，+= 不需要再次给 packages 分配空间，直接添加数据即可
        packages += models
    }
}
